package com.luzhikun.java2;

import com.luzhikun.java1.Person;
import org.junit.Test;

import java.lang.reflect.Constructor;
import java.lang.reflect.Field;
import java.lang.reflect.InvocationTargetException;
import java.lang.reflect.Method;

/**
 * @author shkstart
 * @create 2021-03-04 19:01
 */
/*
 * 获取指定属性 ，方法 ，构造器
 *
 * */
//不需要掌握
public class ReflectionTest {
    public static void main(String[] args) throws IllegalAccessException, InstantiationException, NoSuchFieldException {


        Class cla = Person.class;

        //创建运行时类的对象
        Person person = (Person) cla.newInstance();
        //获得运行时类的指定属性 要求：运行时类的属性为public的
        //通常不采用此方式
        Field age = cla.getField("age");
        //设置运行时类的属性
//        set():参数1：指明参数的对象  参数2：将此属性值设置为多少
        age.set(person, 1001);

        /**
         *
         * 获取当前属性的值
         * get():获取哪个对象的属性值
         */
        int o = (int) age.get(person);
        System.out.println(o);

    }

    /*
     *
     * 如何操作运行时类的指定属性  -- 需要掌握
     * */
    @Test
    public void test1() throws IllegalAccessException, InstantiationException, NoSuchFieldException {

        Class clazz = Person.class;
        //1.创建运行时类的对象
        Person person = (Person) clazz.newInstance();

        //2.通过getDeclaredField（）方式获取运行时类的指定属性
        Field name = clazz.getDeclaredField("sala");

        //3.设置当前属性可访问
        name.setAccessible(true);

        //4.对获取的属性进行修改和输出
        name.set(person, "小明");
        System.out.println(name.get(person));


    }

    /*
     *
     * 如何操作运行时类的指定方法
     * */
    @Test
    public void test2() throws IllegalAccessException, InstantiationException, NoSuchMethodException, InvocationTargetException {
        Class clazz = Person.class;
        //1.创建运行时类的对象
        Person person = (Person) clazz.newInstance();
        /*
         * 2.获取运行时类的指定方法
         * getDeclaredMethod()： 参数1：指明获取的方法的名称 参数2：指明获取的方法的形参列表
         * */
        Method method = clazz.getDeclaredMethod("test1", String.class);
        //3.保证当前方法是可访问的
        method.setAccessible(true);
        //4.调用方法的invoke():参数1：方法的调用者  参数2：给方法形参赋值的实参
        //invoke()的返回值即为对应的类中调用的方法的返回值
        String o = (String) method.invoke(person, "八戒");
        System.out.println(o);

        //如何获取静态方法
        Method test2 = clazz.getDeclaredMethod("test2");
        test2.setAccessible(true);
        Object invoke = test2.invoke(Person.class);
        System.out.println(invoke);
    }

    /*
     *
     * 如何获取运行时类指定构造器
     *
     * */
    @Test
    public void test3() throws NoSuchMethodException, IllegalAccessException, InvocationTargetException, InstantiationException {
        Class clazz = Person.class;
        //1.获取运行时类指定构造器
        Constructor declaredConstructor = clazz.getDeclaredConstructor(String.class);
        declaredConstructor.setAccessible(true);
        Person tom = (Person) declaredConstructor.newInstance("tom");
        System.out.println(tom);


    }
}
